package org.huangrui.juc.day04.locks;


import java.util.concurrent.locks.ReentrantLock;

/**
 * Lock和 synchronized 有以下几点不同:
 *    1.Lock 是一个接口,而 synchronized是Java 中的关键字，synchronized 是内置的语言实现;
 *    2.synchronized 在发生异常时，会自动释放线程占有的锁，因此不会导致死锁现象发生;
 *    而 Lock 在发生异常时，如果没有主动通过 unLock去释放锁，则很可能造成死锁现象，因此使用 Lock 时需要在 finally 块中释放锁。
 *    3.Lock 可以让等待锁的线程响应中断，而 synchronized 却不行，
 *    使用 synchronized 时，等待的线程会一直等待下去,不能够响应中断;
 *    4.通过 Lock 可以知道有没有成功获取锁，而 synchronized 却无法办到。
 *    5.Lock 可以提高多个线程进行读操作的效率。
 *        在性能上来说，如果竟争资源不激烈，两者的性能是差不多的，而当竟争资源
 *        非常激烈时(即有大量线程同时竞争)，此时 Lock的性能要远远优于synchronized.
 * @Author hr
 * @Create 2024-03-31 04:37
 */
public class T01_SaleTicket {
    //第二步 创建多个线程，调用资源类的操作方法
    //创建三个线程
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(()-> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"AA").start();

        new Thread(()-> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"BB").start();

        new Thread(()-> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"CC").start();
    }
}
//第一步  创建资源类，定义属性和和操作方法
class Ticket {
    //票数量
    private int number = 30;

    //创建可重入锁
    private final ReentrantLock lock = new ReentrantLock(true);
    //卖票方法
    public void sale() {
        //上锁
        lock.lock();
        try {
            //判断是否有票
            if(number > 0) {
                System.out.println(Thread.currentThread().getName()+" ：卖出"+(number--)+" 剩余："+number);
            }
        } finally {
            //解锁
            lock.unlock();
        }
    }
}